#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <assert.h>
#include <rtconfig.h>
#include "board.h"
#include "at32f435_437.h"
#include "offchip_flash.h"
#include "drv_qspi.h"

#ifdef BSP_USING_QSPI1
#include <sfud.h>
#include "spi_flash_sfud.h"

// #define OFFCHIP_FLASH_TEST

#ifdef OFFCHIP_FLASH_TEST

#define TEST_SIZE    (4 * 1024)
static int flash_test_addr[] = {
     0 * 1024 * 1024,  1 * 1024 * 1024,  2 * 1024 * 1024,  3 * 1024 * 1024,  
     4 * 1024 * 1024,  5 * 1024 * 1024,  6 * 1024 * 1024,  7 * 1024 * 1024,
     8 * 1024 * 1024,  9 * 1024 * 1024, 10 * 1024 * 1024, 11 * 1024 * 1024, 
    12 * 1024 * 1024, 13 * 1024 * 1024, 14 * 1024 * 1024, 15 * 1024 * 1024,
};
#define TEST_ADDR_NUM (sizeof(flash_test_addr) / sizeof(flash_test_addr[0]))

static int write_and_check(int addr, const char *wbuf, int wlen, char *rbuf, int rlen)
{
    int ret = 0;
    int size = (wlen < rlen) ? wlen : rlen;
    do
    {
        ret = offchip_flash_erase(addr, size);
        if (ret != size)
        {
            ret = 1;
            break;
        }
        ret = offchip_flash_write(addr, wbuf, size);
        if (ret != size)
        {
            ret = 2;
            break;
        }
        ret = offchip_flash_read(addr, rbuf, size);
        if (ret != size)
        {
            ret = 3;
            break;
        }
        ret = rt_memcmp(wbuf, rbuf, size);
        if (ret)
        {
            ret = 4;
        }
    } while (0);
    return ret;
}

int offchip_flash_test(void)
{
    int i = 0;
    int result = 0;
    rt_kprintf("start offchip flash test\r\n");
    // 分配内存空间
    rt_uint8_t *wbuf = rt_malloc(TEST_SIZE);
    rt_uint8_t *rbuf = rt_malloc(TEST_SIZE);
    // 检查内存空间是否分配成功
    RT_ASSERT(wbuf);
    RT_ASSERT(rbuf);
    // 填充随机数
    for (i = 0; i < TEST_SIZE; i += 4)
    {
        wbuf[i + 0] = rand() & 0xFF;
        wbuf[i + 1] = rand() & 0xFF;
        wbuf[i + 2] = rand() & 0xFF;
        wbuf[i + 3] = rand() & 0xFF;
    }
    // 往指定地址写入数据，并检查写入是否正确
    for (i = 0; (i < TEST_ADDR_NUM) && (!result); i++)
    {
        result = write_and_check(flash_test_addr[i], wbuf, TEST_SIZE, rbuf, TEST_SIZE);
    }
    if (result)
    {
        // 写入不正确，打印错误地址
        rt_kprintf("offchip flash test failed on addr 0x%X!\r\n", flash_test_addr[i]);
    }
    else
    {
        rt_kprintf("offchip flash test success!\r\n");
    }
    // 释放内存空间
    rt_free(wbuf);
    rt_free(rbuf);
    return result;
}

INIT_APP_EXPORT(offchip_flash_test);

#endif // !#ifdef OFFCHIP_FLASH_TEST

#endif // !#ifdef BSP_USING_QSPI1
